package it.poste.il.compensatore.service.impl;

import it.poste.il.compensatore.entities.Message;
import it.poste.il.compensatore.entities.MessageBody;
import it.poste.il.compensatore.entities.MessageStatus;
import it.poste.il.compensatore.entities.Operation;
import it.poste.il.compensatore.entities.SDPRequest;
import it.poste.il.compensatore.service.DataManagerService;
import it.poste.il.compensatore.service.MessageBodyService;
import it.poste.il.compensatore.service.MessageService;
import it.poste.il.compensatore.service.MessageStatusService;
import it.poste.il.compensatore.service.OperationService;
import it.poste.il.compensatore.service.SDPRequestService;
import it.poste.il.compensatore.utilities.Constant.DEF_VERIFY_RESULT;
import it.poste.il.compensatore.utilities.LogFactory;
import it.poste.il.compensatore.utilities.LoggerCompensatore;

import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

@Service("dataManagerService")
public class DataManagerServiceImpl implements DataManagerService {
	
	private MessageService messageService;
	private MessageBodyService messageBodyService;
	private MessageStatusService messageStatusService;
	private SDPRequestService sdpRequestService;
	

	private LoggerCompensatore loggerF;
	

	public MessageService getMessageService() {
		return messageService;
	}

	public void setMessageService(MessageService messageService) {
		this.messageService = messageService;
	}

	public SDPRequestService getSdpRequestService() {
		return sdpRequestService;
	}

	public void setSdpRequestService(SDPRequestService sdpRequestService) {
		this.sdpRequestService = sdpRequestService;
	}

	private OperationService operationService;
	
	public OperationService getOperationService() {
		return operationService;
	}

	public void setOperationService(OperationService operationService) {
		this.operationService = operationService;
	}
	
	public MessageStatusService getMessageStatusService() {
		return messageStatusService;
	}

	public void setMessageStatusService(MessageStatusService messageStatusService) {
		this.messageStatusService = messageStatusService;
	}
	
	public MessageBodyService getMessageBodyService() {
		return messageBodyService;
	}

	public void setMessageBodyService(MessageBodyService messageBodyService) {
		this.messageBodyService = messageBodyService;
	}


	public LoggerCompensatore getLoggerF() {
		return loggerF;
	}

	public void setLoggerF(LoggerCompensatore loggerF) {
		this.loggerF = loggerF;
	}
	
	/**
	 * Method storeMsg.
	 * Return message Id.
	 * @return messageId value;
	 */
	public synchronized MessageBody storeMsg(String msg, SDPRequest sdpRequest){
		LoggerCompensatore logger=(LoggerCompensatore)loggerF.getLogger(this);
		Message message = new Message();
		
		//SDPRequest
		logger.info("set requestId");
		SDPRequest sdpRequestSaved = sdpRequestService.save(sdpRequest);
		logger.info("requestId saved " + sdpRequestSaved.getId());
		message.setSdpRequestId(sdpRequestSaved);
		
		//happy path
		logger.debug("set rigth message type");
		message.setType(0);
		
		logger.debug("read l'operation and link to msg");
		//Operation
		Long idOperation = 2000L;
		Operation opList = operationService.retrieveByID(idOperation);
		logger.debug("*******************************class " + opList.getObjHelper());
		message.setOperationId(opList);

		logger.debug("set message status");
		//MessageStatus 1 = sending in progress
		Long idMessageStatus = 1000L;
		MessageStatus messageStatus = messageStatusService.loadByID(idMessageStatus);
		//messageStatus.setDescription("sending in progress");
		message.setStatusId(messageStatus);
		
		logger.debug("message to save");
		message = messageService.save(message);
		logger.debug("message saved " + message.getType() +" " + message.getId());
		
		logger.debug("build body");
		//MessageBody
		MessageBody messageBody = new MessageBody();
		logger.debug("link message");
		messageBody.setInputMessage(msg);
		logger.debug("link message class");
		messageBody.setMessage(message);
		logger.debug("linked message");

		messageBody = messageBodyService.save(messageBody);
		logger.debug("message body saved");
		return messageBody;
	}
		
	/**
	 * Method verifyRequest.
	 * Return verify result. 1 if not duplicate,2 to cancel, 3 to riallign
	 * @return check result;
	 */
	public synchronized DEF_VERIFY_RESULT verifyRequest(SDPRequest requestId, String fase){
		LoggerCompensatore logger=(LoggerCompensatore)loggerF.getLogger(this);
		SDPRequest req = new SDPRequest();
		
		DEF_VERIFY_RESULT result=DEF_VERIFY_RESULT.NOT_VALID;
		logger.info("start verify");
		
		//entity SDPRequest no count
		req.setAccountingDate(requestId.getAccountingDate());
		req.setBranch(requestId.getBranch());
		req.setNumberOperationPdl(requestId.getNumberOperationPdl());
		req.setWorkingStationId(requestId.getWorkingStationId());
		
		//message with SDPRequest req
		Message msg = new Message();
		msg.setSdpRequestId(req);
		
		logger.info("build msg with requestid");
		
		//change status to computed
		MessageStatus msgStatus = new MessageStatus();
		Long idMessageStatus = 1002L;
		msgStatus.setId(idMessageStatus);
		msg.setStatusId(msgStatus);
		logger.info("build msg with status ESEGUITO");
		
		//happy path
		msg.setType(1);
		logger.info("build msg with happy path");
		
	
		logger.info("load last msg new query");
		
		List<SDPRequest> sdpReqNew = sdpRequestService.loadLastCounter(req);
		logger.info("nuova query");
		logger.info("nuova query count resultset"+ sdpReqNew.size());
//		logger.info("**** first id " + sdpReqNew.get(0).getId());
		
		//read id last request
		int counter=0;
		if(sdpReqNew.size()!=0){
			counter = sdpReqNew.get(0).getCounter();
		}
		logger.info("counter DB " + counter);
		//message counter SDP
		int counterRequest = requestId.getCounter();
		logger.info("counter incoming message "+ counterRequest);
		
		//change return type
		if(fase.equals("D")){//DISPOSITIVA
			if(counterRequest==counter+1){
				logger.info("compute");
				result=DEF_VERIFY_RESULT.COMPUTE;
			} else if(counterRequest == counter){
				logger.info("cancel");
				DEF_VERIFY_RESULT.CANCEL.setVerifyCode(sdpReqNew.get(0).getId().toString());
				result=DEF_VERIFY_RESULT.CANCEL;
			} else if(counterRequest < counter || counterRequest > counter+1){
				logger.info("riallign");
				result=DEF_VERIFY_RESULT.RIALLIGN;
			}
		} else {// INFORMATIVA
			if(counterRequest==counter){
				logger.info("compute");
				//ok compute
				result=DEF_VERIFY_RESULT.COMPUTE;
			} else if(counterRequest == counter-1){
				logger.info("cancel");
				DEF_VERIFY_RESULT.CANCEL.setVerifyCode(sdpReqNew.get(0).getId().toString());
				result=DEF_VERIFY_RESULT.CANCEL;
			} else if(counterRequest < counter-1 || counterRequest > counter){
				logger.info("riallign");
				//riallign
				result=DEF_VERIFY_RESULT.RIALLIGN;
			}
			
		}
			
		return result;
	
	}
	
	
	/**
	 * Method createAvoidMessage.
	 * Return cancel message FOR requestId.
	 * @return Cancel message;
	 */
	public String createAvoidMessage(String requestId){
		return "avoid";
	}
	
	/**
	 * Method changeStatus.
	 * Change message status.
	 * @param message to changer status
	 * @return update result
	 */
	public boolean changeStatus(Message message, Long status){
		MessageStatus newStatus = new MessageStatus();
		newStatus.setId(status);
		message.setStatusId(newStatus);
		messageService.update(message);
		return true;
	}
	
}
